package com.jnzc.ocr.serv.shop.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.google.common.collect.Lists;
import com.jnzc.ocr.common.bean.Tree;
import com.jnzc.ocr.common.utils.ArrayHandleUtils;
import com.jnzc.ocr.common.utils.DateUtils;
import com.jnzc.ocr.common.utils.TreeUtils;
import com.jnzc.ocr.common.utils.ValidateUtils;
import com.jnzc.ocr.dependencies.serv.mybatis.MybatisServiceImpl;
import com.jnzc.ocr.serv.shop.entity.ShopProduct;
import com.jnzc.ocr.serv.shop.entity.ShopProductAttr;
import com.jnzc.ocr.serv.shop.filter.ShopProductAttrFilter;
import com.jnzc.ocr.serv.shop.mapper.ShopProductAttrMapper;
import com.jnzc.ocr.serv.shop.service.ShopProductAttrService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.jnzc.ocr.serv.shop.vo.ShopProductAttrSaveVo;
import com.jnzc.ocr.serv.shop.vo.ShopProductSaveVo;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author zhangcm
 * @version 1.0, 2017-09-29
 */
@Service
public class ShopProductAttrServiceImpl extends MybatisServiceImpl<ShopProductAttrMapper, ShopProductAttr, ShopProductAttrFilter> implements ShopProductAttrService {

    @Override
    protected void fillEntityWrapper(EntityWrapper<ShopProductAttr> ew, ShopProductAttrFilter filter) {
        ShopProductAttr entity = new ShopProductAttr();
        entity.setId(filter.getId());
        entity.setShopId(filter.getShopId());
        entity.setParentId(filter.getParentId());
        entity.setCategoryId(filter.getCategoryId());
        entity.setProductId(filter.getProductId());
        ew.setEntity(entity);
        if(CollectionUtils.isNotEmpty(filter.getIdList())) {
            ew.in("id", filter.getIdList());
        }
        if(CollectionUtils.isNotEmpty(filter.getParentIdList())) {
            ew.in("parent_id", filter.getParentIdList());
        }
        if(null != filter.getNullParentId() && filter.getNullParentId()) {
            ew.isNull("parent_id");
        } else if(null != filter.getNullParentId() && !filter.getNullParentId()) {
            ew.isNotNull("parent_id");
        }
        if(null != filter.getProductIdWithNull()) {
            ew.and("(product_id = {0} or product_id is null)", filter.getProductIdWithNull());
        }
        if(null != filter.getCategoryIdWithNull()) {
            ew.and("(category_id = {0} or category_id is null)", filter.getCategoryIdWithNull());
        }
    }

    @Override
    public List<Tree<ShopProductAttr>> listTree(Long shopId) {
        ValidateUtils.isId(shopId);
        ShopProductAttrFilter filter = new ShopProductAttrFilter();
        filter.setShopId(shopId);
        filter.setOrderBy("id");
        List<ShopProductAttr> list = super.list(filter);
        return this.createTree(list);
    }

    @Override
    public List<Tree<ShopProductAttr>> listTree(Long parentId, Long categoryId, Long shopId) {
        ValidateUtils.isId(parentId, "产品ID");
        ValidateUtils.isId(categoryId, "产品分类ID");
        ValidateUtils.isId(shopId, "店铺ID");
        ShopProductAttrFilter filter = new ShopProductAttrFilter();
        filter.setProductIdWithNull(parentId);
        filter.setCategoryIdWithNull(categoryId);
        filter.setShopId(shopId);
        filter.setOrderBy("id");
        List<ShopProductAttr> list = super.list(filter);
        return this.createTree(list);
    }

    @Override
    public ShopProductAttr find(Long id, Long parentId, Long shopId) {
        ValidateUtils.isId(id);
        ShopProductAttrFilter filter = new ShopProductAttrFilter();
        filter.setId(id);
        if(null != parentId) {
            filter.setParentId(parentId);
        } else {
            filter.setNullParentId(true);
        }
        filter.setShopId(shopId);
        return super.findNotNull(filter);
    }

    @Override
    public List<Long> listIdByParentId(Long parentId, Long shopId) {
        ValidateUtils.isId(parentId);
        ShopProductAttrFilter filter = new ShopProductAttrFilter();
        filter.setSelectBy("id");
        filter.setParentId(parentId);
        filter.setShopId(shopId);
        List<ShopProductAttr> list = super.list(filter);
        return ArrayHandleUtils.readAttrList(list, "id");
    }

    @Override
    public List<Long> listIdByProductId(Long productId, Long shopId) {
        ValidateUtils.isId(productId);
        ShopProductAttrFilter filter = new ShopProductAttrFilter();
        filter.setSelectBy("id");
        filter.setProductId(productId);
        filter.setShopId(shopId);
        List<ShopProductAttr> list = super.list(filter);
        return ArrayHandleUtils.readAttrList(list, "id");
    }

    @Override
    @Transactional
    public ShopProductAttr save(ShopProductAttrSaveVo param, Long shopId) {
        ValidateUtils.isId(shopId);
        List<Long> oldIdList = Lists.newArrayList();
        if(null != param.getAttr().getId()) {
            oldIdList = this.listIdByParentId(param.getAttr().getId(), shopId);
        }
        ShopProductAttr obj = save(param.getAttr(), param, 1, null, shopId);
        for (int i = 0; i < param.getAttr().getChildList().size(); i++) {
            ShopProductAttrSaveVo.Attr childAttrParam = param.getAttr().getChildList().get(i);
            if(null != childAttrParam.getId()) {
                oldIdList.remove(childAttrParam.getId());
            }
            save(childAttrParam, param, i + 1, obj, shopId);
        }
        if(CollectionUtils.isNotEmpty(oldIdList)){
            this.delete(oldIdList, shopId);
        }
        return obj;
    }

    @Override
    public void save(List<ShopProductSaveVo.Sku> paramList, ShopProduct product) {
        List<Long> oldAttrIdList = this.listIdByProductId(product.getId(), product.getShopId());
        for (ShopProductSaveVo.Sku param : paramList) {
            ValidateUtils.notEmpty(param.getAttrList(), "属性列表");
            for (ShopProductSaveVo.Attr attrParam : param.getAttrList()) {
                ValidateUtils.notNull(attrParam.getName(), "属性名称");
                ShopProductAttrSaveVo saveVo = new ShopProductAttrSaveVo();
                saveVo.setProductId(product.getId());
                ShopProductAttrSaveVo.Attr attrSaveVo = new ShopProductAttrSaveVo.Attr();
                attrSaveVo.setId(attrParam.getId());
                attrSaveVo.setName(attrParam.getName());
                saveVo.setAttr(attrSaveVo);
                ShopProductAttr obj = save(saveVo, product.getShopId());
                attrParam.setId(obj.getId());
                oldAttrIdList.remove(obj.getId());
            }
        }
        if(CollectionUtils.isNotEmpty(oldAttrIdList)) {
            this.delete(oldAttrIdList, product.getShopId());
        }
    }

    private ShopProductAttr save(ShopProductAttrSaveVo.Attr attrParam, ShopProductAttrSaveVo param, Integer sort, ShopProductAttr parent, Long shopId) {
        ValidateUtils.notEmpty(attrParam.getName(), 20, "属性名称");
        Long parentId = null != parent ? parent.getId() : null;
        ShopProductAttr obj;
        if(null != attrParam.getId()) {
            obj = this.find(attrParam.getId(), parentId, shopId);
        } else {
            obj = new ShopProductAttr();
            obj.setShopId(shopId);
            obj.setParentId(parentId);
            obj.setCreateTime(DateUtils.getNow());
        }
        if(null != parent) {
            obj.setParentName(parent.getName());
        }
        obj.setCategoryId(param.getCategoryId());
        obj.setProductId(param.getProductId());
        obj.setName(attrParam.getName());
        obj.setSort(sort);
        super.save(obj);
        return obj;
    }

    @Override
    public void delete(Long id, Long shopId) {
        ValidateUtils.isId(id);
        this.delete(Lists.newArrayList(id), shopId);
    }

    @Override
    public void deleteByProductId(Long productId, Long shopId) {
        List<Long> idList = this.listIdByProductId(productId, shopId);
        this.delete(idList, shopId);
    }

    private void delete(List<Long> idList, Long shopId) {
        if(CollectionUtils.isEmpty(idList)) {
            return;
        }
        ShopProductAttrFilter filter = new ShopProductAttrFilter();
        filter.setParentIdList(idList);
        filter.setShopId(shopId);
        List<ShopProductAttr> list = this.list(filter);
        List<Long> parentIdList = ArrayHandleUtils.readAttrList(list, "id");
        this.delete(parentIdList, shopId);
        // 删除属性
        ShopProductAttrFilter delFilter = new ShopProductAttrFilter();
        delFilter.setIdList(idList);
        delFilter.setShopId(shopId);
        super.delete(delFilter);
    }

    List<Tree<ShopProductAttr>> createTree(List<ShopProductAttr> list) {
        Tree<ShopProductAttr> tree = TreeUtils.createTree(list, "id", "parentId", "sort");
        return tree.getChildrenList();
    }
}
